home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / pcutils / os2 / show3d / source / show3d.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-31  |  10.2 KB  |  459 lines

  1. #include "easy.h"
  2. #include "show3d.h"
  3. #include "queue.h"
  4.  
  5. #include <math.h>
  6.  
  7. Program program; // must be in every program
  8.  
  9. BitmapPS *bitmap=0; // bitmap for the picture
  10.  
  11. double eyes=0.5; // eye distance
  12. double pagesize=0.8; // size of printer page
  13. int resolution=2; // lazer resolution (1=300 DPI, 2=150 DPI)
  14. int screencolors=2;
  15.  
  16. class Cut
  17. // Berechnet die Musterverläufe für Schnitte durch die Figur.
  18. // Dies ist abhängig von der gewählten Figur.
  19. {   protected :
  20.     Thread *T;
  21.     double Eyes;
  22.     public :
  23.     virtual void getcut (double y, int refs[], int width, Thread &t) {}
  24.     int expected () { return T->expected(); }
  25. };
  26.  
  27. class FunctionCut : public Cut
  28. {    public :
  29.     virtual void getcut (double y, int refs[], int width, Thread &t);
  30.     virtual double f (double x, double y) { return 0; }
  31. };
  32.  
  33. void FunctionCut::getcut (double y, int refs[], int width, Thread &t)
  34. {   int i;
  35.     double x=2,xd,z,xl,xlold,factor,xold;
  36.     int l,r;
  37.     int first=1;
  38.     xd=1.0/width;
  39.     for (i=0; i<width; i++) refs[i]=-1;
  40.     while (x>-2)
  41.     {   xold=x;
  42.         again :
  43.         x-=xd;
  44.         if (t.expected()) return;
  45.         z=-1+f(x,y);
  46.         if (!first) xlold=xl;
  47.         xl=(2*(x+eyes)/(2-z)+1-eyes)/2*width;
  48.         if (!first)
  49.         {    factor=fabs(xl-xlold);
  50.             if (factor<0.5) factor=0.5;
  51.             xd/=factor/0.9;
  52.             if (factor>1)
  53.             {    x=xold; goto again;
  54.             }
  55.         }
  56.         first=0;
  57.         l=floor(xl);
  58.         r=floor((2*(x-eyes)/(2-z)+1+eyes)/2*width);
  59.         if (l<0 || l>=width) continue;
  60.         if (r>=width) continue;
  61.         if (refs[l]<0) refs[l]=r;
  62.         else if (refs[l]>r) refs[l]=r;
  63.     }
  64. }
  65.  
  66. class WaveFunctionCut : public FunctionCut
  67. {    public :
  68.     virtual double f (double x, double y)
  69.     {    double r=sqrt(x*x+y*y);
  70.         return cos(12*r)*exp(-2*r)*0.2;
  71.     }
  72. } wave;
  73.  
  74. class AppleFunctionCut : public FunctionCut
  75. {    public :
  76.     virtual double f (double x, double y);
  77. } apple;
  78.  
  79. double AppleFunctionCut::f (double x, double y)
  80. {    double zre,zim,h;
  81.     int i;
  82.     x-=0.7;
  83.     zre=x; zim=y;
  84.     for (i=0; i<8; i++)
  85.     {     h=x+zre*zre-zim*zim;
  86.         zim=y+2*zre*zim; zre=h;
  87.     }
  88.     double r=zre*zre+zim*zim;
  89.     if (r<4) r=4;
  90.     r=log(r)-log(4);
  91.     if (r>200) r=200;
  92.     return (r/200)*0.2;
  93. }
  94.  
  95. class BallFunctionCut : public FunctionCut
  96. {    public :
  97.     virtual double f (double x, double y);
  98. } ball;
  99.  
  100. double BallFunctionCut::f (double x, double y)
  101. {    double r=sqrt(x*x+y*y);
  102.     if (r>0.7) return 0;
  103.     else return sqrt(0.7*0.7-r*r)/2;
  104. }
  105.  
  106. double ff (double x, double y);
  107. class FFunctionCut : public FunctionCut
  108. {    public :
  109.     virtual double f (double x, double y)
  110.     {    return ff(x,y);
  111.     }
  112. } function;
  113.  
  114. class MyThread : public Thread
  115. {   double Done; // done percentage
  116.     public :
  117.     MyThread (int (*f) (Parameter)) : Thread(f) {}
  118.     double done () { return Done; }
  119.     void done (double done) { Done=done; }
  120. };
  121.  
  122. Cut *actcut=&wave;
  123.  
  124. class Image
  125. // This class generates the image line by line
  126. // can be on a bitmap, a PM printer, or a raw printer
  127. {   protected :
  128.     long Width,Height;
  129.     public :
  130.     virtual void point (long i, ULONG color) {}
  131.     virtual void nextline () {}
  132.     virtual long width () { return Width; }
  133.     virtual long height () { return Height; }
  134.     virtual void erase () {}
  135. };
  136.  
  137. class BitmapImage : public Image
  138. {   BitmapPS *Ps;
  139.     long line;
  140.     public :
  141.     BitmapImage (BitmapPS &ps) : Ps(&ps)
  142.     {    line=ps.height()-1;
  143.         Height=ps.height(); Width=ps.width();
  144.     }
  145.     virtual void point (long i, ULONG color)
  146.     {    Ps->point(i,line,color);
  147.     }
  148.     virtual void nextline () { line--; }
  149.     virtual void erase () { Ps->erase(); }
  150. };
  151.  
  152. class PrinterImage : public Image
  153. {   PrinterPS *Ps;
  154.     long line;
  155.     unsigned char *Data;
  156.     public :
  157.     PrinterImage (PrinterPS &ps) : Ps(&ps)
  158.     {    line=ps.height()-1;
  159.         Height=ps.height(); Width=ps.width();
  160.         Data=new unsigned char [Width/8+1];
  161.         memset(Data,0,Width/8);
  162.     }
  163.     ~PrinterImage ()
  164.     {    delete Data;
  165.     }
  166.     virtual void point (long i, ULONG color);
  167.     virtual void nextline ();
  168. };
  169.  
  170. void PrinterImage::point (long i, ULONG color)
  171. {    if (color!=Colors::black) return;
  172.     Data[i>>3]|=(unsigned char)(128>>(i&7));
  173. }
  174.  
  175. void PrinterImage::nextline ()
  176. {    long i,total=Width/8,w;
  177.     for (i=0; i<total; i+=128)
  178.     {   Ps->move(i*8,line);
  179.         w=128;
  180.         if (i+w>total) w=total-i;
  181.         Ps->image(w*8,1,Data+i);
  182.     }
  183.     memset(Data,0,Width/8);
  184.     line--;
  185. }
  186.  
  187. class LaserImage : public Image
  188. {    Queue *Q;
  189.     unsigned char *Data;
  190.     public :
  191.     LaserImage ();
  192.     ~LaserImage ();
  193.     virtual void point (long i, ULONG color);
  194.     virtual void nextline ();
  195. };
  196.  
  197. LaserImage::LaserImage ()
  198. {    Q=new Queue("HPLaserJ","Show3D");
  199.     *Q << "\x1B""*t150R"; // 300 DPI resolution
  200.     double lasersize=2400;
  201.     Width=Height=((int)(lasersize/resolution*pagesize)/8)*8;
  202.     *Q << Format("\x1B""*p%dx%dY",
  203.         (int)((lasersize-Width*resolution)/2),
  204.         (int)((lasersize*sqrt(2.0)-Height*resolution)/2));
  205.         // center raster image
  206.     *Q << "\x1B""*r1A"; // start raster graphics left flush
  207.     Data=new unsigned char[4096];
  208.     memset(Data,0,Width/8);
  209. }
  210.  
  211. LaserImage::~LaserImage ()
  212. {   *Q << "\x1B""*rB"; // end raster graphics
  213.     delete Data;
  214.     delete Q;
  215. }
  216.  
  217. void LaserImage::point (long i, ULONG color)
  218. {    if (color!=Colors::black) return;
  219.     Data[i>>3]|=(unsigned char)(128>>(i&7));
  220. }
  221.  
  222. void LaserImage::nextline ()
  223. {      *Q << Format("\x1B""*b%dW",Width/8); // start raster line
  224.     Q->write(Data,Width/8);
  225.     memset(Data,0,Width/8);
  226. }
  227.  
  228. class Figure
  229. // controls drawing an image.
  230. // Figure is used in a separate thread and generated by it.
  231. {   int *Left;
  232.     ULONG *Color;
  233.     int Width,Height,Colors;
  234.     MyThread *T; // the generating thread
  235.     Cut *F;
  236.     public :
  237.     Figure (MyThread &thread, Cut &f, int nc=screencolors)
  238.         : Colors(nc),T(&thread),F(&f) {}
  239.     void draw (Image &image);
  240.     void getcut (double y);
  241.     void colors (int i) { Colors=i; }
  242.     int expected () { return T->expected(); }
  243. };
  244.  
  245. void Figure::draw (Image &image)
  246. {   int i,row;
  247.     image.erase();
  248.     Width=image.width(); Height=image.height();
  249.     Left=new int[Width];
  250.     Color=new ULONG[Width];
  251.     for (row=0; row<Height; row++)
  252.     {    F->getcut(1.5-3*(double)row/Height,Left,Width,*T);
  253.         if (expected()) return;
  254.         for (i=Width-1; i>=0; i--)
  255.         {    if (Left[i]<0 || Left[i]==Left[i+1])
  256.             {    switch (rand()%Colors)
  257.                 {    case 0 : Color[i]=Colors::white; break;
  258.                     case 1 : Color[i]=Colors::black; break;
  259.                     case 2 : Color[i]=Colors::blue; break;
  260.                     case 3 : Color[i]=Colors::red; break;
  261.                     default : Color[i]=Colors::green;
  262.                 }
  263.             }
  264.             else
  265.             {    Color[i]=Color[Left[i]];
  266.             }
  267.             image.point(i,Color[i]);
  268.             if (expected()) return;
  269.         }
  270.         image.nextline();
  271.         T->done((double)row/Height);
  272.     }
  273.     delete Color;
  274.     delete Left;
  275. }
  276.  
  277. class MyWindow : public StandardWindow
  278. {   int Activate; // must be activated
  279.     public :
  280.     MyWindow () :
  281.         StandardWindow(ID_Window,"Show 3D",
  282.             StandardWindow::normal|StandardWindow::menu),Activate(0)
  283.     {    init();
  284.     }
  285.     virtual void sized ();
  286.     virtual void redraw (PS &ps);
  287.     void activate () { Activate=1; sized(); }
  288.     virtual int close ();
  289.     virtual void timer (int i); // copy bitmap to screen every 1 sec
  290. } mywindow;
  291. Menu menu(mywindow);
  292. Help help (mywindow,ID_Help,"show3d.hlp","");
  293.  
  294. void MyWindow::redraw (PS &ps)
  295. // this is easy
  296. {   bitmap->copy(ps);
  297. }
  298.  
  299. void MyWindow::timer (int i)
  300. // called every 1 sec
  301. {    bitmap->copy(WindowPS(mywindow));
  302. }
  303.  
  304. int draw (Parameter p);
  305. MyThread drawthread (draw); // the drawing thread
  306.  
  307. int draw (Parameter p)
  308. {   Figure figure(drawthread,*actcut);
  309.     BitmapImage image(*bitmap);
  310.     mywindow.starttimer(1);
  311.     drawthread.done(0);
  312.     figure.draw(image);
  313.     mywindow.update();
  314.     mywindow.stoptimer();
  315.     return 0;}
  316.  
  317. int print (Parameter p);
  318. MyThread printthread (print); // the printing thread
  319.  
  320. int print (Parameter p)
  321. // called from printing thread
  322. {   Figure figure(printthread,*actcut,2);
  323.     PrinterPS printer;
  324.     long x,y,w,h;
  325.     x=printer.width()*(1-pagesize)/2;
  326.     w=((pagesize*printer.width())/8+1)*8;
  327.     y=printer.height()/2-w/2;
  328.     h=w;
  329.     printer.offset(x,y);
  330.     printer.clip(0,0,w,h);
  331.     PrinterImage image(printer);
  332.     printthread.done(0);
  333.     figure.draw(image);
  334.     Beep(440,1);
  335.     return 0;
  336. }
  337.  
  338. int laser (Parameter p);
  339. MyThread laserthread (laser); // the printing thread
  340.  
  341. int laser (Parameter p)
  342. // called from printing thread
  343. {   Figure figure(laserthread,*actcut,2);
  344.     LaserImage image;
  345.     figure.draw(image);
  346.     Beep(440,1);
  347.     return 0;
  348. }
  349.  
  350. void MyWindow::sized ()
  351. {   drawthread.wait();
  352.     if ((bitmap &&
  353.         (width()!=bitmap->width() || height()!=bitmap->height()))
  354.             || !bitmap)
  355.     {    if (bitmap) delete bitmap;
  356.         bitmap=new BitmapPS (mywindow);
  357.     }
  358.     if (!Activate) return;
  359.     drawthread.start();
  360.     update();
  361. }
  362.  
  363. void start ()
  364. {    drawthread.wait();
  365.     drawthread.start();
  366. }
  367.  
  368. int abortprint ()
  369. {    if (printthread.started())
  370.     {   char msg[256];
  371.         sprintf(msg,"%2.3g percent done.\nAbort Print?",
  372.             printthread.done()*100);
  373.         if (Question(msg,"3D")==Answers::no) return 0;
  374.         printthread.wait();
  375.     }    return 1;
  376. }
  377.  
  378. int abortlaser ()
  379. {    if (laserthread.started())
  380.     {   char msg[256];
  381.         sprintf(msg,"%2.3g percent done.\nAbort Laser Print?",
  382.             laserthread.done()*100);
  383.         if (Question(msg,"3D")==Answers::no) return 0;
  384.         laserthread.wait();
  385.     }    return 1;
  386. }
  387.  
  388. int MyWindow::close ()
  389. {     if (!abortprint()) return 0;
  390.     if (!abortlaser()) return 0;
  391.     drawthread.wait();    return 1;
  392. }
  393.  
  394. void doexit ()
  395. {   mywindow.quit();
  396. }
  397.  
  398. void doprint ()
  399. {   if (!abortprint()) return;
  400.     printthread.wait();    printthread.start();
  401. }
  402.  
  403. void dolaserjet ()
  404. {   if (!abortlaser()) return;
  405.     laserthread.wait();    laserthread.start();
  406. }
  407.  
  408. void dowave ()
  409. {    actcut=&wave; start();
  410. }
  411.  
  412. void doapple ()
  413. {    actcut=&apple; start();
  414. }
  415.  
  416. void doball ()
  417. {    actcut=&ball; start();
  418. }
  419.  
  420. void dofunction ()
  421. {    actcut=&function; start();
  422. }
  423.  
  424. void dooptions ()
  425. {   drawthread.wait();
  426.     Dialog options(mywindow,ID_Options,help,400);
  427.     SliderItem slider(IDO_Eyes,options,eyes*100);
  428.     SliderItem page(IDO_Pagesize,options,pagesize*100);
  429.     options.carryout();
  430.     if (options.result()!=DID_OK) return;
  431.     eyes=slider/100.0;
  432.     pagesize=page/100.0;
  433.     mywindow.update();
  434.     start();
  435. }
  436.  
  437. void dogeneral ()
  438. {    help.general();
  439. }
  440.  
  441. int main ()
  442. {   mywindow.size(350,350);
  443.     mywindow.top();
  444.     mywindow.activate();
  445.     menu.add(IDM_Exit,doexit);
  446.     menu.add(IDM_Print,doprint);
  447.     menu.add(IDM_Laserjet,dolaserjet);
  448.     menu.add(IDM_Wave,dowave);
  449.     menu.add(IDM_Apple,doapple);
  450.     menu.add(IDM_Options,dooptions);
  451.     menu.add(IDM_Ball,doball);
  452.     menu.add(IDM_General,dogeneral);
  453.     menu.add(IDM_Function,dofunction);
  454.     program.loop();
  455.     delete bitmap;
  456.     return 0;
  457. }
  458.  
  459.